package com.sanjiaozhou.gameserver.webNetty;

import com.backblaze.erasure.FecAdapt;
import com.backblaze.erasure.fec.Snmp;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import kcp.ChannelConfig;
import kcp.KcpListener;
import kcp.KcpServer;
import kcp.Ukcp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.nio.charset.StandardCharsets;

/**
 * 处理字符串传输的KCP服务端
 */
@Component
public class KcpJsonServer implements KcpListener {

    private static final Logger logger = LoggerFactory.getLogger(KcpJsonServer.class);

    private Ukcp lastKcp;

    @PostConstruct
    public void init(){
        // 配置KCP参数
        ChannelConfig channelConfig = new ChannelConfig();
        channelConfig.nodelay(true, 40, 2, true);  // 快速模式
        channelConfig.setSndwnd(512);  // 发送窗口大小
        channelConfig.setRcvwnd(512);  // 接收窗口大小
        channelConfig.setMtu(512);     // 最大传输单元
        channelConfig.setFecAdapt(new FecAdapt(3, 1));  // FEC前向纠错
        channelConfig.setAckNoDelay(true);  // ACK不延迟
        channelConfig.setTimeoutMillis(100000);  // 超时时间
        channelConfig.setUseConvChannel(true);  // 使用会话通道
        channelConfig.setCrc32Check(true);     // CRC校验
        channelConfig.setConv(66);

        // 启动KCP服务器
        KcpServer kcpServer = new KcpServer();
        kcpServer.init(this, channelConfig, 20003);
        logger.info("启动netty");
    }

    public void sendLast(String content){
        if(null == lastKcp){
            logger.info("没有连接");
            return;
        }
        // 原样返回消息给客户端
        ByteBuf response = null;
        try {
            response = createMessage(500, content);
            lastKcp.write(response);
        } finally {
            if (null != response) {
                response.release();
            }
        }
    }

    @Override
    public void onConnected(Ukcp ukcp) {
        lastKcp = ukcp;
        logger.info("有连接进来" + Thread.currentThread().getName() + ukcp.user().getRemoteAddress());
    }

    @Override
    public void handleReceive(ByteBuf buf, Ukcp kcp) {
        try {
            // 读取消息序号
            int seqNum = buf.readShort();

            // 读取消息长度
            int msgLength = buf.readShort();

            // 读取消息内容
            byte[] msgBytes = new byte[msgLength];
            buf.readBytes(msgBytes);
            String message = new String(msgBytes, StandardCharsets.UTF_8);

            logger.info("收到消息 #" + seqNum + ": " + message);

            // 收到结束标志
            if (seqNum == -1) {
                logger.info("收到传输结束信号");
//                kcp.close();
                return;
            }

            // 原样返回消息给客户端
            ByteBuf response = createMessage(seqNum, "服务器已收到: " + message);
            kcp.write(response);
            response.release();

        } catch (Exception e) {
            logger.error("处理消息时出错:");
            e.printStackTrace();
        }
    }

    // 创建响应消息
    private ByteBuf createMessage(int seqNum, String content) {
        byte[] contentBytes = content.getBytes(StandardCharsets.UTF_8);
        ByteBuf buf = Unpooled.buffer(4 + contentBytes.length);

        buf.writeShort(seqNum);          // 写入序号
        buf.writeShort(contentBytes.length); // 写入长度
        buf.writeBytes(contentBytes);    // 写入内容

        return buf;
    }

    @Override
    public void handleException(Throwable ex, Ukcp kcp) {
        logger.error("发生异常:");
        ex.printStackTrace();
    }

    @Override
    public void handleClose(Ukcp kcp) {
        logger.info("连接已关闭");
        logger.info("通信统计:\n{}", Snmp.snmp.toString());
        Snmp.snmp = new Snmp();  // 重置统计
    }
}